/**
 *	@file	blist.h
 *	
 *	@brief	the bidirection list implement.
 *
 *	@author	Forrest.Zhang.
 */

#ifndef	FZ_BLIST_H
#define	FZ_BLIST_H

typedef struct blist {
	struct blist	*p;
	struct blist	*n;
} blist_t;

typedef struct blist_head {
	struct blist	*h;
	struct blist	*t;
	size_t		n;
} blist_head_t;

#define	BLIST_DEF_HEAD(lh)				\
	blist_head_t lh = {.h = NULL, .t = NULL, n = 0}
#define	BLIST_INIT_HEAD(lh)				\
	((lh)->h = (lh)->t = NULL, (lh)->n = 0)

#define	BLIST_INIT(l)	((l)->p = (l)->n = NULL)
#define	BLIST_ELEM(l, t, m)	\
	((l)?(t)(((void *)(l))-((void *)&((t)NULL)->m)):NULL)
	
#define	BLIST_LENGTH(lh)	((l)->n)
#define	BLIST_IS_EMPTY(lh)	((l)->n == 0)


static inline int 
blist_add_head(blist_head_t *lh, blist_t *l)
{
	l->p = NULL;
	l->n = lh->h;
	lh->h = l;
	if (!lh->t) lh->t = l;
	lh->n++;
}

static inline int 
blist_add_tail(blist_head_t *lh, blist_t *l)
{
	l->n = NULL;
	l->p = lh->t;
	if (!lh->p) lh->p = l;
	lh->n++;
}

static inline void * 
blist_del(blist_head_t *lh, blist_t *l)
{
	if (l->p)
		l->p->n = l->n;
	else
		lh->p = l->n;

	if (l->n)
		l->n->p = l->p;
	else
		lh->t = l->p;
	
	lh->n--;
	l->p = l->n = NULL;
	return l;
}

static inline int 
blist_join(blist_head_t *dlh, blist_head_t *slh)
{
	/* link 2 elems: dlh->t <-> slh->h */
	if (dlh->t) 
		dlh->t->n = slh->h;
	if (slh->h) 
		slh->h->p = dlh->t;
	
	/* set correct header */
	if (!dlh->h)
		dlh->h = slh->h;
	/* set correct tail */
	if (slh->t)
		dlh->t = slh->t;

	dlh->n += slh->n;
	BLIST_INIT_HEAD(slh);
	return 0;
}

#endif	/* end of FZ_BLIST_H */

